#ifndef SFLOG_H
#define SFLOG_H
#include <QGuiApplication>
#include <QDate>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#ifndef Q_OS_WASM
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#endif
#include <QMutex>
#include <QQueue>
#include <QTextStream>

#include <iostream>
static const char  Red[] = "\033[31m";
static const char  Green[] = "\033[32m";
static const char  Yellow[] = "\033[33m";
static const char  Blue[] = "\033[36m";
static const char  White[] = "\033[37m";
static const char  ColorEnd[] = "\033[0m";
static QElapsedTimer g_startupTimer;
const char* logLevel[] = { Green, Blue, Yellow, Red};

class SfLogger {
public:
    enum class LOGModle {
        terminalOUT = 0X01,
        fileOUT = 0X02,
        CallBack = 0X04
    };
    Q_DECLARE_FLAGS(LOGModles, LOGModle)
    typedef struct {
        QString time;
        QString info;
        QString msg;
        const char* l;
    }frame;
    static LOGModles modle;
private:
    static const qint64 MAX_FILE_SIZE = 10 * 1024 * 1024;  // 100 MB
    static const int MAX_BACKUP_FILES = 100;  // 最多保留的备份文件数

    SfLogger()
    {
        std::cout<<QString("log:%1").arg(logDirPath).toUtf8().constData()<<std::endl<< std::flush;
        qInfo()<<QString("log:%1").arg(logDirPath);
        g_startupTimer.start();
        createLogFile();
    }
    SfLogger(const SfLogger &) = delete;
    SfLogger &operator=(const SfLogger &) = delete;
    ~SfLogger() {
                    #ifndef Q_OS_WASM
        writeFuture.waitForFinished();
        file.close();
#endif
    }

    void write() {
        while (true) {
            frame msg;
            {
                QMutexLocker locker(&mutex);
                if (queue.isEmpty()) break;

                msg = queue.dequeue();
            }
            // 检查文件大小
            if (isFileSizeExceeded()) {
                rotateLogFile();
            }
            // 写入日志
            if (file.isOpen()) {
                QTextStream stream(&file);
                //std::cout<<msg.info.toStdString()<<msg.msg.toStdString() << std::endl;
                stream << msg.info <<msg.msg << Qt::endl;
            }
        }
    }
public:
    static void customMessageHandler(QtMsgType type,
                                     const QMessageLogContext &context,
                                     const QString &msg) {
        frame formattedMessage;
        formattedMessage.msg = msg;
        formattedMessage.info =     QString("%1 ").arg(g_startupTimer.elapsed() / 1000.0,  // 值
                                                   12,                                   // 字段宽度（含小数点）
                                                   'f',                                 // 定点格式
                                                   3,                                   // 3 位小数
                                                   QLatin1Char(' '));                   // 左侧补空格
        switch (type) {
        case QtDebugMsg:
            formattedMessage.info +="[D] ";
            break;
        case QtInfoMsg:
            formattedMessage.info += "[I] ";
            break;
        case QtWarningMsg:
            formattedMessage.info += "[W] ";
            break;
        case QtCriticalMsg:
            formattedMessage.info += "[E] ";
            break;
        case QtFatalMsg:
            formattedMessage.info += "[F] ";
            break;
        default:
            break;
        }
        auto logger = instance();
        {
            QMutexLocker locker(&logger->mutex);
            logger->queue.enqueue(formattedMessage);
        }
                    #ifndef Q_OS_WASM
        if (!logger->writeFuture.isRunning()) {

            logger->writeFuture = QtConcurrent::run([](){
                instance()->write();
            });

        }
                #endif
    }

    static SfLogger *instance() {
        static SfLogger logger;
        return &logger;
    }

private:
    void createLogFile() {
        QDir logDir(logDirPath);
        if (!logDir.exists()) {
            logDir.mkpath(".");
        }

        QString logFilePath = logDirPath + "/" +
                              QDateTime::currentDateTime().toString("yyyy-MM-dd") +
                              ".log";

        file.setFileName(logFilePath);

        if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) {
            qDebug() << "Failed to open log file:" << file.errorString();
        }
        else
        {
            QTextStream stream(&file);
            stream << Qt::endl;
            stream << "Log file created at: "
                   << QDateTime::currentDateTime().toString(Qt::TextDate)<< Qt::endl;
        }
    }

    bool isFileSizeExceeded() const { return file.size() >= MAX_FILE_SIZE; }

    void rotateLogFile() {
        file.close();  // 先关闭当前文件
        QString baseName = QFileInfo(file.fileName()).baseName();
        QString dirPath = QFileInfo(file.fileName()).absolutePath();

        // 查找下一个可用的备份文件名
        for (int i = MAX_BACKUP_FILES; i > 0; --i) {
            QString oldFileName =
                QString("%1/%2-%3.log").arg(dirPath).arg(baseName).arg(i);
            if (QFile::exists(oldFileName)) {
                // 如果存在，则重命名为下一个序号
                if (i == MAX_BACKUP_FILES) {
                    QFile::remove(oldFileName);  // 超过最大文件数，删除最旧的
                } else {
                    QString newFileName =
                        QString("%1/%2-%3.log").arg(dirPath).arg(baseName).arg(i + 1);
                    QFile::rename(oldFileName, newFileName);
                }
            }
        }

        // 将当前日志文件重命名为 -1
        QString newFileName = QString("%1/%2-1.log").arg(dirPath).arg(baseName);
        QFile::rename(file.fileName(), newFileName);

        // 重新创建新日志文件
        createLogFile();
    }

private:

    QMutex mutex;
    QQueue<frame> queue;
    QFile file;
#ifndef Q_OS_WASM
    QFuture<void> writeFuture;

    const  QString logDirPath =(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)+"/pm/log");
#else

    const  QString logDirPath;
#endif

};
SfLogger::LOGModles SfLogger::modle = SfLogger::LOGModle::fileOUT;
#endif // SFLOG_H
